home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 4 / QRZ Ham Radio Callsign Database - Volume 4.iso / files / dsp / 56ktools / dspkgctr.z / dspkgctr / gcc / config / out-dsp16.c < prev    next >
C/C++ Source or Header  |  1992-06-08  |  53KB  |  2,497 lines

  1. /* subroutines for insn-output.c for motorola dsp561XX.
  2.    copyright ( c ) 1988 free software foundation, inc.
  3.  
  4.    $Id: out-dsp16.c,v 1.2 91/09/18 15:34:49 jeff Exp $
  5.  
  6. this file is part of gnu cc.
  7.  
  8. gnu cc is distributed in the hope that it will be useful,
  9. but without any warranty.  no author or distributor
  10. accepts responsibility to anyone for the consequences of using it
  11. or for whether it serves any particular purpose or works at all,
  12. unless he says so in writing.  refer to the gnu cc general public
  13. license for full details.
  14.  
  15. everyone is granted permission to copy, modify and redistribute
  16. gnu cc, but only under the conditions described in the
  17. gnu cc general public license.     a copy of this license is
  18. supposed to have been given to you along with gnu cc so you
  19. can know your rights and responsibilities.  it should be in a
  20. file named copying.  among other things, the copyright notice
  21. and this notice must be preserved on all copies.  */
  22.  
  23.  
  24. #ifndef file
  25. #include <stdio.h>
  26. #endif
  27.  
  28. #include <string.h>
  29. #if defined ( _MSDOS )
  30. extern void *malloc( );
  31. #endif
  32.  
  33. #include <ctype.h>
  34.  
  35. #include "flags.h"
  36. #include "tree.h"
  37. #if ! defined( _INTELC32_ )
  38. #include "hard-reg-set.h"
  39. #else
  40. #include "hardrset.h"
  41. #endif
  42.  
  43. char mem_space = 'y';
  44. char memory_model = 'y';
  45.  
  46. func_attributes current_func_info = FUNC_NO_INFO;
  47.  
  48. static char local_call_used_regs[] = CALL_USED_REGISTERS;
  49. enum reg_class regno_reg_class ( );
  50.  
  51. int FirstSave;
  52.  
  53. void
  54. PushRegs ( file )
  55.     FILE* file;
  56. {
  57.     int reg_index;
  58.  
  59.     FirstSave = -1;
  60.     
  61.     for ( reg_index = 0; reg_index < FIRST_PSEUDO_REGISTER; ++ reg_index )
  62.     {
  63.     if ( regs_ever_live[ reg_index ] && 
  64.         ! local_call_used_regs[ reg_index ] )
  65.     {
  66.         if ( 0 > FirstSave )
  67.         {
  68.         FirstSave = reg_index;
  69.         }
  70.         
  71.         if ( DST_REGS == REGNO_REG_CLASS ( reg_index ))
  72.         {
  73.         if ( 'l' == memory_model )
  74.         {
  75.             fprintf ( file, "\
  76.     move    %c10,l:(r3)+\n", *reg_names[ reg_index ] );
  77.         }
  78.         else
  79.         {
  80.             fprintf ( file, "\
  81.     move    %s0,%c:(r3)+\n\
  82.     move    %s1,%c:(r3)+\n", reg_names[ reg_index ], mem_space,
  83.                  reg_names[ reg_index ], mem_space );
  84.         }
  85.         
  86.         }
  87.         else if ( SRC_REGS == REGNO_REG_CLASS ( reg_index ) ||
  88.              MPY_REGS == REGNO_REG_CLASS ( reg_index ))
  89.         {
  90.         if ( 'l' == memory_model )
  91.         {
  92.             /* try to save x or y as a pair. */
  93.             if ( reg_index & 1 )
  94.             {
  95.             /* x1 or y1 */
  96.             if ( ! ( regs_ever_live[ reg_index - 1 ] &&
  97.                 ! local_call_used_regs[ reg_index - 1 ] ))
  98.             {
  99.                 /* was the 0 portion saved ? if so, then we
  100.                    don't need to do anything, else save the 1 ! */
  101.  
  102.                 fprintf ( file, "\
  103.     move    %s,%c:(r3)+\n", reg_names[ reg_index ], mem_space );
  104.             }
  105.             }
  106.             else
  107.             {
  108.             /* x0 or y0 */
  109.             if ( regs_ever_live[ reg_index + 1 ] && 
  110.                 ! local_call_used_regs[ reg_index + 1 ] )
  111.             {
  112.                 /* are we also saving the 1 portion ? if so,
  113.                    save the 1 as well as the 0 with an l: move.
  114.                    otherwise, just save the 0. */
  115.                 fprintf ( file, "\
  116.     move    %c,l:(r3)+\n", *reg_names[ reg_index ] );
  117.             }
  118.             else
  119.             {
  120.                 fprintf ( file, "\
  121.     move    %s,%c:(r3)+\n", reg_names[ reg_index ], mem_space );
  122.             }
  123.             }
  124.         }
  125.         else
  126.         {
  127.             fprintf ( file, "\
  128.     move    %s,%c:(r3)+\n", reg_names[ reg_index ], mem_space );
  129.         }
  130.         }
  131.         else
  132.         {
  133.         fprintf ( file, "\
  134.     move    %s,%c:(r3)+\n", reg_names[ reg_index ], mem_space );
  135.         }
  136.         
  137.     }
  138.     }
  139. }
  140.  
  141. void
  142. PopRegs ( file )
  143.     FILE* file;
  144. {
  145.     int reg_index = FIRST_PSEUDO_REGISTER;
  146.     int first_save = 0;
  147.     
  148. #define SAVE_CHECK \
  149. {\
  150.     if ( ! first_save )\
  151.     {\
  152.     first_save = 1;\
  153.     fprintf ( file, "\tmove    (r3)-\n" );\
  154.     }\
  155. }
  156.  
  157.  
  158.     while ( -- reg_index >= 0 )
  159.     {
  160.     if ( regs_ever_live[ reg_index ] && 
  161.         ! local_call_used_regs[ reg_index ] )
  162.     {
  163.         SAVE_CHECK;
  164.         
  165.         if ( DST_REGS == REGNO_REG_CLASS ( reg_index ))
  166.         {
  167.         if ( reg_index == FirstSave )
  168.         {
  169.             if ( 'l' == memory_model )
  170.             {
  171.             fprintf ( file, "\
  172.     move    l:(r3),%c\n", *reg_names[ reg_index ] );
  173.             }
  174.             else
  175.             {
  176.             fprintf ( file, "\
  177.     move    %c:(r3)-,%s\n\
  178.     move    %c:(r3),%s0\n", mem_space, reg_names[ reg_index ],
  179.                  mem_space, reg_names[ reg_index ] );
  180.             }
  181.         }
  182.         else
  183.         {
  184.             if ( 'l' == memory_model )
  185.             {
  186.             fprintf ( file, "\
  187.     move    l:(r3)-,%c\n", *reg_names[ reg_index ] );
  188.             }
  189.             else
  190.             {
  191.             fprintf ( file, "\
  192.     move    %c:(r3)-,%s\n\
  193.     move    %c:(r3)-,%s0\n", mem_space, reg_names[ reg_index ],
  194.                  mem_space, reg_names[ reg_index ] );
  195.             }
  196.         }
  197.         }
  198.         else if ( SRC_REGS == REGNO_REG_CLASS ( reg_index ) ||
  199.              MPY_REGS == REGNO_REG_CLASS ( reg_index ))
  200.         {
  201.         if ( 'l' == memory_model )
  202.         {
  203.             if ( reg_index & 1 )
  204.             {
  205.             /* x1 or y1 */
  206.             if ( ! ( regs_ever_live[ reg_index -1 ] && 
  207.                 ! local_call_used_regs[ reg_index - 1 ] ))
  208.             {
  209.                 /* if the 0 portion wasn't saved we need to
  210.                    restore the 1, otherwise do nothing. */
  211.  
  212.                 if ( reg_index == FirstSave )
  213.                 {
  214.                 fprintf ( file, "\
  215.     move    %c:(r3),%s\n", mem_space, reg_names[ reg_index ] );
  216.                 }
  217.                 else
  218.                 {
  219.                 fprintf ( file, "\
  220.     move    %c:(r3)-,%s\n", mem_space, reg_names[ reg_index ] );
  221.                 }
  222.             }
  223.             }
  224.             else
  225.             {
  226.             /* x0 or y0 */
  227.             if ( regs_ever_live[ reg_index + 1 ] && 
  228.                 ! local_call_used_regs[ reg_index + 1 ] )
  229.             {
  230.                 /* if the 1 portion was also saved, then we
  231.                    need to to do an l: restore, otherwise a y:. */
  232.  
  233.                 if ( reg_index == FirstSave )
  234.                 {
  235.                 fprintf ( file, "\
  236.     move    l:(r3),%c\n", *reg_names[ reg_index ] );
  237.                 }
  238.                 else
  239.                 {
  240.                 fprintf ( file, "\
  241.     move    l:(r3)-,%c\n", *reg_names[ reg_index ] );
  242.                 }
  243.             }
  244.             else
  245.             {
  246.                 if ( reg_index == FirstSave )
  247.                 {
  248.                 fprintf ( file, "\
  249.     move    %c:(r3),%s\n", mem_space, reg_names[ reg_index ] );
  250.                 }
  251.                 else
  252.                 {
  253.                 fprintf ( file, "\
  254.     move    %c:(r3)-,%s\n", mem_space, reg_names[ reg_index ] );
  255.                 }
  256.             }
  257.             }
  258.         }
  259.         else
  260.         {
  261.             if ( reg_index == FirstSave )
  262.             {
  263.             fprintf ( file, "\
  264.     move    %c:(r3),%s\n", mem_space, reg_names[ reg_index ] );
  265.             }
  266.             else
  267.             {
  268.             fprintf ( file, "\
  269.     move    %c:(r3)-,%s\n", mem_space, reg_names[ reg_index ] );
  270.             }
  271.         }
  272.         }
  273.         else
  274.         {
  275.         if ( reg_index == FirstSave )
  276.         {
  277.             fprintf ( file, "\
  278.     move    %c:(r3),%s\n", mem_space, reg_names[ reg_index ] );
  279.         }
  280.         else
  281.         {
  282.             fprintf ( file, "\
  283.     move    %c:(r3)-,%s\n", mem_space, reg_names[ reg_index ] );
  284.         }
  285.         }
  286.     }
  287.     }
  288. }
  289.  
  290. int
  291. go_if_legitimate_address ( mode, x, strict )
  292.     int mode;
  293.     rtx x;
  294.     int strict;
  295. {
  296.     /* constant pointer */
  297.  
  298.     if ( CONSTANT_ADDRESS_P ( x ) )
  299.     {
  300.     return 1;
  301.     }
  302.  
  303.     /* note that REG_OK_STRICT may NOT be defined here! */
  304.     /* register pointer */
  305.  
  306.     if ( REG_P ( x ) && 
  307.     (( strict ) ? 
  308.      ( REGNO_OK_FOR_INDEX_P ( REGNO ( x ))) :
  309.      ( REG_OK_FOR_INDEX_P ( x ))))
  310.     {
  311.     return 1;
  312.     }
  313.     
  314.     /* register arithmetic */
  315.     
  316.     switch ( GET_CODE ( x ) )
  317.     {
  318.     case SUBREG:
  319.     return go_if_legitimate_address ( mode, XEXP ( x, 0 ), strict );
  320.                      
  321.     case POST_DEC:
  322.     case POST_INC:
  323.     case PRE_INC:
  324.     case PRE_DEC:
  325.     if ( REG_P ( XEXP ( x, 0 )) && 
  326.         (( strict ) ? 
  327.          ( REGNO_OK_FOR_INDEX_P ( REGNO ( XEXP ( x, 0 )))) :
  328.          ( REG_OK_FOR_INDEX_P ( XEXP ( x, 0 )))))
  329.     {
  330.         return 1;
  331.     }
  332.     break;
  333.     
  334.     case PLUS:
  335.     if ( REG_P ( XEXP ( x, 0 )) && 
  336.         ( Pmode == GET_MODE ( XEXP ( x, 0 ))) &&
  337.         ( CONST_INT == GET_CODE ( XEXP ( x, 1 ))) &&
  338.         (( strict ) ? 
  339.          ( REGNO_OK_FOR_INDEX_P ( REGNO ( XEXP ( x, 0 )))) :
  340.          ( REG_OK_FOR_INDEX_P ( XEXP ( x, 0 )))))
  341.     {
  342.         return 1;
  343.     }
  344.  
  345.     if ( REG_P ( XEXP ( x, 1 )) && 
  346.         ( Pmode == GET_MODE ( XEXP ( x, 1 ))) &&
  347.         ( CONST_INT == GET_CODE ( XEXP ( x, 0 ))) &&
  348.         (( strict ) ? 
  349.          ( REGNO_OK_FOR_INDEX_P ( REGNO ( XEXP ( x, 1 )))) :
  350.          ( REG_OK_FOR_INDEX_P ( XEXP ( x, 1 )))))
  351.     {
  352.         return 1;
  353.     }
  354.     }
  355.     return 0;
  356. }
  357.  
  358. void
  359. print_operand_address ( file, addr )
  360.     FILE* file;
  361.     rtx addr;
  362. {
  363.     register rtx reg0;
  364.     register rtx reg1;
  365.  
  366.     switch ( GET_CODE ( addr ) )
  367.     {
  368.  
  369.     case REG:
  370.     fprintf ( file, "(%s)", reg_names[ REGNO ( addr )] );
  371.     break;
  372.  
  373.     case POST_INC:
  374.     fprintf ( file, "(%s)+", reg_names[ REGNO ( XEXP ( addr, 0 ) )] );
  375.     break;
  376.  
  377.     case POST_DEC:
  378.     fprintf ( file, "(%s)-", reg_names[ REGNO ( XEXP ( addr, 0 ) )] );
  379.     break;
  380.  
  381.     case PLUS:
  382.     abort ( );
  383.     
  384.     default:
  385.     output_addr_const ( file, addr );
  386.     }
  387. }
  388.  
  389. void
  390. notice_update_cc ( exp, insn )
  391.     rtx exp;
  392.     rtx insn;
  393. {
  394.     if ( PARALLEL == GET_CODE ( exp ))
  395.     {
  396.     rtx call_insn = XVECEXP ( exp, 0, 0 );
  397.     if ( GET_CODE ( call_insn ) == SET &&
  398.          GET_CODE ( XEXP ( call_insn, 1 )) == CALL )
  399.     {
  400.         cc_status.flags = 0;
  401.         cc_status.value1 = cc0_rtx;
  402.         cc_status.value2 = gen_rtx ( REG, SImode, DSP16_A_REGNUM );
  403.         cc_status.mdep = CC_SIGNED;
  404.     }
  405.     else
  406.     {
  407.         CC_STATUS_INIT;
  408.     }
  409.     }
  410.     else if ( SET == GET_CODE ( exp ))
  411.     {
  412.     switch ( GET_CODE ( SET_DEST ( exp )))
  413.     {
  414.     case CC0:
  415.         cc_status.flags = 0;
  416.         cc_status.value1 = SET_DEST ( exp );
  417.         cc_status.value2 = SET_SRC ( exp );
  418.         break;
  419.         
  420.     case REG:
  421.         CC_STATUS_INIT;
  422.     }
  423.     }
  424.     else
  425.     {
  426.     CC_STATUS_INIT;
  427.     }
  428. }
  429.  
  430. rtx
  431. next_cc_relevancy ( insn )
  432.     rtx insn;
  433. {
  434.     rtx peek = NEXT_INSN ( insn );
  435.     
  436.     for ( ; NULL != peek; peek = NEXT_INSN ( peek ))
  437.     {
  438.     switch ( GET_CODE( peek ))
  439.     {
  440.     case JUMP_INSN:
  441.     case CALL_INSN:
  442.     case CODE_LABEL:
  443.     case BARRIER:
  444.         return peek;
  445.         
  446.     case INSN:
  447.         if (( PARALLEL == GET_CODE ( PATTERN ( peek ))) &&
  448.         ( SET == GET_CODE ( XVECEXP ( PATTERN ( peek ), 0, 0 ))) &&
  449.         ( 0 == strcmp ( GET_RTX_FORMAT ( GET_CODE ( XEXP ( XVECEXP ( PATTERN ( peek ), 0, 0 ), 1 ))), "ee" )) &&
  450.         ( cc0_rtx == XEXP ( XEXP ( XVECEXP ( PATTERN ( peek ), 0, 0 ), 1 ), 0 )))
  451.         {
  452.         return peek;
  453.         }
  454.     }
  455.     }
  456.     return insn;
  457. }
  458.  
  459. enum mdep_cc_info
  460. next_cc_use ( insn )
  461.     rtx insn;
  462. {
  463.     enum rtx_code jump_code;
  464.     rtx peek = NEXT_INSN ( insn );
  465.     
  466.     for ( ; NULL != peek; peek = NEXT_INSN ( peek ))
  467.     {
  468.     if ( JUMP_INSN == GET_CODE ( peek ))
  469.     {
  470.         break;
  471.     }
  472.     if ( CALL_INSN == GET_CODE ( peek ) ||
  473.         CODE_LABEL == GET_CODE ( peek ) ||
  474.         BARRIER == GET_CODE ( peek ) )
  475.     {
  476.         return CC_UNKNOWN;
  477.     }
  478.     if ( INSN == GET_CODE ( peek ) &&
  479.         PARALLEL == GET_CODE ( PATTERN ( peek )) &&
  480.         SET == GET_CODE ( XVECEXP ( PATTERN ( peek ), 0, 0 )) &&
  481.         0 == strcmp ( GET_RTX_FORMAT ( GET_CODE ( XEXP ( XVECEXP ( PATTERN ( peek ), 0, 0 ), 1 ))), "ee" ) &&
  482.         ( cc0_rtx == XEXP ( XEXP ( XVECEXP ( PATTERN ( peek ), 0, 0 ), 1 ), 0 ) ||
  483.          cc0_rtx == XEXP ( XEXP ( XVECEXP ( PATTERN ( peek ), 0, 0 ), 1 ), 1 )))
  484.     {
  485.         jump_code = GET_CODE ( XEXP ( XVECEXP ( PATTERN ( peek ), 0, 0 ), 1 ));
  486.         
  487.         if ( GEU == jump_code || GTU == jump_code || LEU == jump_code
  488.         || LTU == jump_code )
  489.         {
  490.         return CC_UNSIGNED;
  491.         }
  492.         else
  493.         {
  494.         return CC_SIGNED;
  495.         }
  496.     }
  497.     }
  498.  
  499.     if (( NULL == peek ) || 
  500.     ( JUMP_INSN != GET_CODE ( peek )) ||
  501.     ( SET != GET_CODE ( PATTERN ( peek ))) ||
  502.     ( IF_THEN_ELSE != GET_CODE ( XEXP ( PATTERN ( peek ), 1 ))))
  503.     {
  504.     return CC_UNKNOWN;
  505.     }
  506.     jump_code = GET_CODE ( XEXP ( XEXP ( PATTERN ( peek ), 1 ), 0 ));
  507.     
  508.     if ( GEU == jump_code || GTU == jump_code || LEU == jump_code
  509.     || LTU == jump_code || EQU == jump_code || NEU == jump_code )
  510.     {
  511.     return CC_UNSIGNED;
  512.     }
  513.     else
  514.     {
  515.     return CC_SIGNED;
  516.     }
  517. }
  518.  
  519. /* hard_regno_mode_ok -
  520.  * this global function implements the tm-m56k.h file macro of the same name.
  521.  * a 1 is returned if regno can be used to hold a value of type mode.
  522.  */
  523.  
  524. int
  525. hard_regno_mode_ok ( regno, mode )
  526.     int regno;
  527.     int mode;
  528. {
  529.     switch ( mode )
  530.     {
  531.     case VOIDmode:
  532.     return 1;
  533.     
  534.     case SFmode:
  535.     case DFmode:
  536.     case DImode:
  537.     /* for doubles, floats, and longs, we need 48-bit registers. */
  538.     if ( DSP16_X0_REGNUM == regno || DSP16_Y0_REGNUM == regno ||
  539.         DSP16_A_REGNUM == regno || DSP16_B_REGNUM == regno )
  540.     {
  541.         return 1;
  542.     }
  543.     else
  544.     {
  545.         return 0;
  546.     }
  547.     break;
  548.  
  549.     case PSImode:
  550.     /* for pointers we can use any register. */
  551.     return 1;
  552.     
  553.     default:
  554.     /* for all other cases, we assume that a 16-bit reg is needed. */
  555.     if ( regno < 6 )
  556.     {
  557.         return 1;
  558.     }
  559.     else
  560.     {
  561.         return 0;
  562.     }
  563.     break;
  564.     }
  565. }
  566.  
  567. /* modes_tieable_p -
  568.  * this global function implements the tm-m56k.h file macro of the same name.
  569.  * a 1 is returned if both modes can always use the same pseudo register.
  570.  */
  571.  
  572. int
  573. modes_tieable_p ( mode1, mode2 )
  574.     int mode1;
  575.     int mode2;
  576. {
  577.     if ( mode1 == mode2 )
  578.     {
  579.     return 1;
  580.     }
  581.     
  582.     switch ( mode1 )
  583.     {
  584.     case SFmode:
  585.     case DFmode:
  586.     case DImode:
  587.     if ( SFmode == mode2 || DFmode == mode2 || DImode == mode2 )
  588.     {
  589.         return 1;
  590.     }
  591.     else
  592.     {
  593.         return 0;
  594.     }
  595.     break;
  596.     }
  597.     return 0;
  598. }
  599.  
  600. /* regno_reg_class -
  601.  * this global function implements the tm-m56k.h file macro of the same name.
  602.  * the class number of the smallest class containing reg number regno is
  603.  * returned.
  604.  */
  605.  
  606. enum reg_class
  607. regno_reg_class ( regno )
  608.     int regno;
  609. {
  610.     switch ( regno )
  611.     {
  612.     case DSP16_X0_REGNUM:
  613.     case DSP16_Y0_REGNUM:
  614.     return MPY_REGS;
  615.     
  616.     case DSP16_X1_REGNUM:
  617.     case DSP16_Y1_REGNUM:
  618.     return SRC_REGS;
  619.  
  620.     case DSP16_A_REGNUM:
  621.     case DSP16_B_REGNUM:
  622.     return DST_REGS;
  623.  
  624.     default:
  625.     if ( regno < 10 )
  626.     {
  627.         return ADDR_REGS;
  628.     }
  629.     return ALL_REGS;
  630.     }
  631. }
  632.  
  633.  
  634. /* reg_class_from_letter -
  635.  * this global function implements the tm-m56k.h file macro of the same name.
  636.  * the class number of the given letter is returned.
  637.  */
  638.  
  639. enum reg_class
  640. reg_class_from_letter ( c )
  641.     char c;
  642. {
  643.     switch ( c )
  644.     {
  645.     case 'S':
  646.     return SRC_REGS;
  647.     case 'D':
  648.     return DST_REGS;
  649.     case 'A':
  650.     return ADDR_REGS;
  651.     case 'R':
  652.     return MPY_REGS;
  653.     
  654.     default:
  655.     return NO_REGS;
  656.     }
  657. }
  658.  
  659. /* reg_class_from_letter -
  660.  * this global function implements the tm-m56k.h file macro of the same name.
  661.  * the max number of consecutive registers needed per mode is returned.
  662.  */
  663.  
  664. int
  665. class_max_nregs ( class, mode )
  666.     int class;
  667.     int mode;
  668. {
  669.     if (( SFmode == mode || DFmode == mode || DImode == mode ) &&
  670.     ( SRC_REGS == class ))
  671.     {
  672.     return 2;
  673.     }
  674.     else
  675.     {
  676.     return 1;
  677.     }
  678. }
  679.  
  680. /* ---------------------------------------------------------------- *\
  681.    
  682.    name         dgetmant
  683.  
  684.    synopsis     dgetmant(dfptval, wordnum)
  685.                 double dfptval;
  686.         int wordnum;
  687.  
  688.    description
  689.       Inputs:
  690.          dfptval = double precision value from which mantissa is extracted
  691.          wordnum:  0 = upper 20 bits (leading 1 suppressed)
  692.          1 = lower 32 bits
  693.  
  694.    return value 
  695.  
  696. \* ---------------------------------------------------------------- */
  697.  
  698. #if 0 
  699. long dgetmant(dfptval, wordnum)
  700. double dfptval;
  701. int    wordnum;
  702. {
  703.    long *ivalptr;
  704.  
  705.    ivalptr = (long *) &dfptval;
  706.  
  707. #if defined( _MSDOS ) || defined( MIPSEL )
  708.    if (wordnum == 0)
  709.       return( ((*(ivalptr+1))) & 0x000fffffL);
  710.    else   /* lower word */
  711.       return( *(ivalptr) );
  712. #else
  713.    if (wordnum == 0)
  714.       return( ((*ivalptr)) & 0x000fffff);
  715.    else   /* lower word */
  716.       return( *(ivalptr+1) );
  717. #endif
  718. }
  719.  
  720.  
  721.  
  722. long dgetexp(dfptval)
  723. double dfptval;
  724. {
  725.    long *ivalptr;
  726.  
  727.    ivalptr = (long *) &dfptval;
  728. #if defined( _MSDOS ) || defined( MIPSEL )
  729.    ivalptr++;
  730. #endif
  731.    return( ((*ivalptr)>>20) & 0x07ff );       /* masks sign bit too */
  732. }
  733.  
  734. union real_extract adjusted_dval;
  735.  
  736. void
  737. dtok ( file, dval )
  738.     FILE* file;
  739.     union real_extract dval;
  740. {
  741.     unsigned long   L_word, H_word, tmp, tmp2, dsgn;
  742.     long   increase_exponent;
  743.     
  744.  
  745.     if ( dval.d == 0 )
  746.     {
  747.     H_word = L_word = 0;
  748.     }
  749.     else
  750.     {
  751.     L_word = dgetexp(dval.d);       /* ieee exponent */
  752.     H_word = dgetmant(dval.d,0);    /* grab upper 20 bits of double */
  753.     tmp2=dgetmant(dval.d,1);        /* lower 32 bits of ieee mantissa */
  754.  
  755.     /* ieee denormalized number */
  756.     if ( L_word == 0 )
  757.     {
  758.         L_word++; /* try it*/
  759.  
  760.         /* normalize it */        
  761.         while ( ! ( H_word & 0x100000 ) )
  762.         {
  763.         L_word -- ;      /* exponent decreases */
  764.         H_word <<= 1 ;   /* shift entire 52 bit ieee mantissa left */
  765.         
  766.         if ( tmp2 & 0x80000000l )
  767.         {
  768.             H_word |= 1 ;
  769.         }
  770.            
  771.         tmp2 <<= 1 ;
  772.         }
  773.     }
  774.  
  775.     /* normalized ieee number with implied leading 1 */
  776.     else
  777.     {
  778.         H_word |= 0x00100000;      /* add leading 1 */
  779.     }
  780.        
  781.     H_word <<= 10;
  782.     tmp = ((tmp2 & 0xc0000000) >> 1);   /* grab lower 2 bits */
  783.     tmp >>= 21;                         /* ------------------- */
  784.     H_word |= tmp;                      /* combine upper and lower */
  785.     increase_exponent=0;
  786.  
  787.     /* round up for 1/2 lsb of kp mantissa */
  788.     if ( tmp2 & 0x20000000l )
  789.     {
  790.         if ( H_word >= 0x7fffff00 )
  791.         {
  792.         increase_exponent = 1;
  793.         H_word += 0x100;
  794.         H_word >>= 1;
  795.         }
  796.         
  797.         else
  798.         {
  799.         H_word += 0x100;
  800.         }
  801.     }
  802.  
  803.  
  804. #if defined( _MSDOS ) || defined( MIPSEL )
  805.     dsgn = ( * (long *) &(dval.i[1]) ) & 0x80000000l;
  806. #else   /* real computers */
  807.     dsgn = ( * (long *) &(dval.i[0]) ) & 0x80000000l;
  808. #endif
  809.  
  810.     /* check for negative value in ieee format */
  811.     if ( dsgn )
  812.     {
  813.         H_word = -H_word;
  814.     }  
  815.        
  816.     H_word >>= 8;
  817.     L_word -= 1023;             /* IEEE double precision bias  */
  818.     L_word += 8191;             /* kevFP little precision bias */
  819.     L_word ++;                  /* lameFP s.xxx..xx */
  820.     L_word += increase_exponent; /* in case rounding modified exponent */
  821.     
  822.     /* negative weird case ( -0.5 == 800000  not c00000 ) */
  823.     if ( (H_word & 0x800000) && (H_word & 0x400000) )
  824.     {
  825.         H_word <<= 1;
  826.         L_word--;
  827.     }  
  828.     }
  829.    
  830.     
  831.     if ( NULL != file )
  832.     {
  833.     if ( 'l' == memory_model )
  834.     {
  835.         fprintf ( file, "\tdc\t$%06x%06x\n", H_word & 0xffffff,
  836.              L_word & 0xffffff );
  837.     }
  838.     else
  839.     {
  840.         fprintf ( file, "\tdc\t$%06x\n\tdc\t$%06x\n", L_word & 0xffffff,
  841.              H_word & 0xffffff );
  842.     }
  843.     }
  844.     
  845.     adjusted_dval.i[1] = ( 0x00ffffff & H_word );
  846.     adjusted_dval.i[0] = ( 0x00ffffff & L_word );
  847. }
  848. #endif
  849.  
  850.  
  851. int
  852. local_first_parm_offset ( fundecl ) 
  853.     tree fundecl;
  854. {
  855.     tree arg_list;
  856.     
  857. #if 0
  858.     if (( NULL == fundecl ) ||
  859.     ( NULL == ( arg_list = DECL_ARGUMENTS ( fundecl ))))
  860.     {
  861.     return -4;
  862.     }
  863.     
  864.     return - int_size_in_bytes ( DECL_ARG_TYPE ( arg_list )) + -3;
  865. #else
  866.     return -2;
  867. #endif    
  868. }
  869.  
  870. void
  871. print_operand ( file, x, code )
  872.     FILE* file;
  873.     rtx x;
  874.     char code;
  875. {
  876.     rtx ensure_pointer_result_size ( );
  877.     rtx ensure_integer_result_size ( );
  878.     
  879.     if ( 'p' == code )
  880.     {
  881.     x = ensure_pointer_result_size ( copy_rtx ( x ));
  882.  
  883.     output_addr_const ( file, x );
  884.     return;
  885.     }
  886.     else if ( 'q' == code )
  887.     {
  888.     x = ensure_integer_result_size ( copy_rtx ( x ));
  889.  
  890.     output_addr_const ( file, x );
  891.     return;
  892.     }
  893.     
  894.     switch ( GET_CODE ( x ) )
  895.     {
  896.     case REG:
  897.     switch ( code )
  898.     {
  899.     case 'd':
  900.         fprintf ( file, "%s", reg_names[ REGNO ( x ) ] );
  901.         break;
  902.         
  903.     case 'e':
  904.         if ( DST_REGS == REGNO_REG_CLASS ( REGNO ( x )))
  905.         {
  906.         if ( MEM_IN_STRUCT_P ( x ))
  907.         {
  908.             /* see comment in final.c */
  909.             fprintf ( file, "%s0", reg_names[ REGNO ( x ) ] );
  910.         }
  911.         else
  912.         {
  913.             fprintf ( file, "%s1", reg_names[ REGNO ( x ) ] );
  914.         }
  915.         }
  916.         else
  917.         {
  918.         fprintf ( file, "%s", reg_names[ REGNO ( x ) ] );
  919.         }
  920.         break;
  921.         
  922.     case 'g':
  923.         fprintf ( file, "%s", reg_names[ REGNO ( x ) ^ 1 ] );
  924.         break;
  925.         
  926.     case 'h':
  927.         fprintf ( file, "%s0", reg_names[ REGNO ( x ) ] );
  928.         break;
  929.  
  930.     case 'i':
  931.         fprintf ( file, "%c", *( reg_names[ REGNO ( x ) ] ));
  932.         break;
  933.  
  934.     case 'j':
  935.         fprintf ( file, "n%c", * ( reg_names[ REGNO ( x ) ] + 1 ));
  936.         break;
  937.         
  938.     case 'k':
  939.         fprintf ( file, "%s2", reg_names[ REGNO ( x ) ] );
  940.         break;
  941.         
  942.     case 'm':
  943.         fprintf ( file, "%c", (reg_names[ REGNO ( x ) ])[0] );
  944.         break;
  945.         
  946.     case 'o':
  947.         fprintf ( file, "%c10", (reg_names[ REGNO ( x ) ])[0] );
  948.         break;
  949.         
  950.     default:
  951.         if ( MEM_IN_STRUCT_P ( x ))
  952.         {
  953.         /* see comment in final.c */
  954.         fprintf ( file, "%s0", reg_names[ REGNO ( x ) ] );
  955.         }
  956.         else
  957.         {
  958.         fprintf ( file, "%s", reg_names[ REGNO ( x ) ] );
  959.         }
  960.         break;
  961.     }
  962.     break;
  963.     
  964.     case MEM:
  965.     switch ( code )
  966.     {
  967.     case 'f':
  968.         /* print out a 'l' instead of an x or y when we need to */
  969.         if (( 'l' == memory_model ) && 
  970.         (( DImode == GET_MODE ( x )) ||
  971.          ( SFmode == GET_MODE ( x )) ||
  972.          ( DFmode == GET_MODE ( x ))))
  973.         {
  974.         fprintf ( file, "l:" );
  975.         }
  976.         else
  977.         {
  978.         fprintf ( file, "%c:", mem_space );
  979.         }
  980.         output_address ( ensure_pointer_result_size 
  981.                 ( copy_rtx ( XEXP ( x, 0 ))));
  982.         break;
  983.         
  984.     default:
  985.         output_address ( ensure_pointer_result_size 
  986.                 ( copy_rtx ( XEXP ( x, 0 ))));
  987.     }
  988.     return;
  989.  
  990.     case CONST_INT:
  991.     if ( 0 == ( INTVAL ( x ) >> 8 ))
  992.     {
  993.         fprintf ( file, "#>$%02x", INTVAL ( x ) );
  994.     }
  995.     else
  996.     {
  997.         fprintf ( file, "#>$%04x", INTVAL ( x ) );
  998.     }
  999.     return;
  1000.  
  1001.     default:
  1002. #if 0
  1003.     fprintf ( file, "#" );
  1004.     if ( CONSTANT_ADDRESS_P ( x ))
  1005.     {
  1006.         output_addr_const ( file, x );
  1007.     }
  1008.     else
  1009.     {
  1010.         output_operand ( x, 'c' );
  1011.     }
  1012. #endif
  1013.     abort ( );
  1014.     }
  1015. }
  1016.  
  1017. void
  1018. simplify_cse_victims ( first )
  1019.     rtx first;
  1020. {
  1021.     rtx point, elem;
  1022.     
  1023.     while ( first )
  1024.     {
  1025.     /* is it a 3 element PARALLEL ? */
  1026.     if (( INSN == GET_CODE ( first )) &&
  1027.         ( point = PATTERN ( first ), PARALLEL == GET_CODE ( point )) &&
  1028.         ( 3 == XVECLEN ( point, 0 )) &&
  1029.  
  1030.         /* is the 1st element a ( SET ( REG ) ( REG / CONST_INT )) ? */
  1031.         ( elem = XVECEXP ( point, 0, 0 ), SET == GET_CODE ( elem )) &&
  1032.         ( REG == GET_CODE ( SET_DEST ( elem ))) &&
  1033.         (( REG == GET_CODE ( SET_SRC ( elem ))) ||
  1034.          ( CONST == GET_CODE ( SET_SRC ( elem ))) ||
  1035.          ( CONST_INT == GET_CODE ( SET_SRC ( elem )))) &&
  1036.  
  1037.         /* is the 2nd element a ( CLOBBER ( REG )) ? */
  1038.         ( elem = XVECEXP ( point, 0, 1 ), CLOBBER == GET_CODE ( elem )) &&
  1039.         ( REG == GET_CODE ( XEXP ( elem, 0 ))) &&
  1040.  
  1041.         /* is the 3rd element a ( CLOBBER ( REG )) ? */
  1042.         ( elem = XVECEXP ( point, 0, 2 ), CLOBBER == GET_CODE ( elem )) &&
  1043.         ( REG == GET_CODE ( XEXP ( elem, 0 ))))
  1044.     {
  1045.         /* we've got a blown-out div template ! substitute with a simple
  1046.            ( SET ( REG ) ( REG / CONST_INT )) (note: really the 1st 
  1047.            element of the parallel). */
  1048.  
  1049.         PATTERN ( first ) = XVECEXP ( point, 0, 0 );
  1050.     }
  1051.     first = NEXT_INSN ( first );
  1052.     }
  1053. }
  1054.  
  1055.  
  1056. static int
  1057. mpy_insn_p ( insn )
  1058.     rtx insn;
  1059. {
  1060.     return (( INSN == GET_CODE ( insn )) &&
  1061.         ( SET == GET_CODE ( PATTERN ( insn ))) &&
  1062.         ( REG == GET_CODE ( SET_DEST ( PATTERN ( insn )))) &&
  1063.         ( MULT == GET_CODE ( SET_SRC ( PATTERN ( insn )))));
  1064. }
  1065.  
  1066. static int
  1067. mac_insn_p ( insn )
  1068.     rtx insn;
  1069. {
  1070.     /* mac +/- shape detector. */
  1071.     return (( INSN == GET_CODE ( insn )) &&
  1072.         ( SET == GET_CODE ( PATTERN ( insn ))) &&
  1073.         ( REG == GET_CODE ( SET_DEST ( PATTERN ( insn )))) &&
  1074.         (( PLUS == GET_CODE ( SET_SRC ( PATTERN ( insn )))) ||
  1075.          ( MINUS == GET_CODE ( SET_SRC ( PATTERN ( insn ))))) &&
  1076.         (( MULT == GET_CODE ( XEXP ( SET_SRC ( PATTERN ( insn )), 0 ))) ||
  1077.          ( MULT == GET_CODE ( XEXP ( SET_SRC ( PATTERN ( insn )), 1 )))));
  1078. }
  1079.  
  1080. static rtx
  1081. mac_addative_input ( mac )
  1082.     rtx mac;
  1083. {
  1084.     return ( MULT == GET_CODE ( XEXP ( SET_SRC ( PATTERN ( mac )), 0 ))) ?
  1085.     XEXP ( SET_SRC ( PATTERN ( mac )), 1 ) :
  1086.         XEXP ( SET_SRC ( PATTERN ( mac )), 0 );
  1087. }
  1088.  
  1089. void
  1090. reduce_norm_freq ( first )
  1091.     rtx first;
  1092. {
  1093.     /* point to the last insn.
  1094.        search up the list for each mac insn:
  1095.            detemine the addative_input.
  1096.        foreach insn in LOG_LINKS( point ):
  1097.            if insn SETs the addative_input, and insn is a mac or mpy, and
  1098.               there are no reload generated references to the operand
  1099.           between these two instructions, then:
  1100.                mark the pointed to mac as not needing input normalization
  1101.            mark the mpy/mac insn as not needing output normalization.
  1102.        
  1103.        the templates for mpy/mac will check for these flags. */
  1104.  
  1105.     rtx last = first, point;
  1106.     
  1107.     /* find the last insn, search up from it */
  1108.     while ( NULL != NEXT_INSN ( last ))
  1109.     {
  1110.     last = NEXT_INSN ( last );
  1111.     }
  1112.  
  1113.     while ( last != first )
  1114.     {
  1115.     if ( mac_insn_p ( last ))
  1116.     {
  1117.         rtx add_in = mac_addative_input ( last );
  1118.         rtx insn_chain = LOG_LINKS ( last );
  1119.         
  1120.         while ( NULL != insn_chain )
  1121.         {
  1122.         rtx this_insn = XEXP ( insn_chain, 0 );
  1123.  
  1124.         if ((( mac_insn_p ( this_insn )) ||
  1125.              ( mpy_insn_p ( this_insn ))) &&
  1126.             ( add_in == SET_DEST ( PATTERN ( this_insn ))) &&
  1127.             ( ! reg_used_between_p ( add_in, this_insn, last )))
  1128.         {
  1129.             /* kludge up: re-use existing flags, in_struct and used, 
  1130.                to inhibit the emission of normalization code at the
  1131.                front and back end of mac (and mpy) instructions. */
  1132.  
  1133.             /* turn off last's pre-norm. */
  1134.             MEM_IN_STRUCT_P ( last ) = 1;
  1135.             
  1136.             /* turn off this_insn's post-norm. */
  1137.             RTX_UNCHANGING_P ( this_insn ) = 1;
  1138.         }
  1139.         insn_chain = XEXP ( insn_chain, 1 );
  1140.         }
  1141.     }
  1142.     last = PREV_INSN ( last );
  1143.     }
  1144. }
  1145.  
  1146. /* this extraneous function is needed because the MetaWare C compiler
  1147.    can't handle the comma operator with pointer values. */
  1148.  
  1149. rtx
  1150. local_function_incoming_arg ( cum, mode, type, named )
  1151.     CUMULATIVE_ARGS cum;
  1152.     enum machine_mode mode;
  1153.     tree type;
  1154.     int named;
  1155. {
  1156.     current_func_info |= FUNC_HAS_STACK_PARMS;
  1157.  
  1158.     return FUNCTION_ARG (cum, mode, type, named);
  1159. }
  1160.  
  1161. #define N_REG_COUNT 4
  1162. #define FIRST_N_REG 6
  1163.  
  1164. static rtx current_n_reg_value[ N_REG_COUNT ];
  1165.  
  1166. void
  1167. clear_n_reg_values ( )
  1168. {
  1169.     int i = N_REG_COUNT;
  1170.     
  1171.     while ( i -- )
  1172.     {
  1173.     current_n_reg_value[i] = NULL;
  1174.     }
  1175. }
  1176.  
  1177. int
  1178. load_n_reg_p ( reg, new_value )
  1179.     rtx reg, new_value;
  1180. {
  1181.     if ( current_n_reg_value[ REGNO ( reg ) - FIRST_N_REG ] &&
  1182.     rtx_equal_p ( current_n_reg_value[ REGNO ( reg ) - FIRST_N_REG ], 
  1183.               new_value ) &&
  1184.     CONSTANT_P ( new_value ))
  1185.     {
  1186.     return 0;
  1187.     }
  1188.     else
  1189.     {
  1190.     current_n_reg_value[ REGNO ( reg ) - FIRST_N_REG ] =  new_value;
  1191.  
  1192.     return 1;
  1193.     }
  1194. }
  1195.     
  1196. /* sort the compares into the signed and unsigned varieties. */
  1197. void
  1198. sort_compares ( insns )
  1199.     rtx insns;
  1200. {
  1201.     while ( insns )
  1202.     {
  1203.     if (( INSN == GET_CODE ( insns )) &&
  1204.         ( SET == GET_CODE ( PATTERN ( insns ))) &&
  1205.         ( cc0_rtx == SET_DEST ( PATTERN ( insns ))) &&
  1206.         ( CC_UNSIGNED == next_cc_use ( insns )))
  1207.     {
  1208.         UNSIGNED_COMPARE_P ( insns ) = 1;
  1209.     }
  1210.     insns = NEXT_INSN ( insns );
  1211.     }
  1212. }
  1213.  
  1214. char*
  1215. move_singleword ( operands )
  1216.     rtx *operands;
  1217. {
  1218.     extern char mem_space;
  1219.     
  1220.     if (( rtx_equal_p ( operands[0], operands[1] )) &&
  1221.     (( REG != GET_CODE ( operands[0] )) ||
  1222.      ( ! MEM_IN_STRUCT_P ( operands[0] ))) &&
  1223.     (( REG != GET_CODE ( operands[1] )) ||
  1224.      ( ! MEM_IN_STRUCT_P ( operands[1] ))))
  1225.     {
  1226.     /* if we're doing a nop move, return a null string. note that
  1227.        an insn could look like a nop move isasmuchas rtx_equal_p returns
  1228.        true; however the MEM_IN_STRUCT_P kludge used by alter_subreg ( )
  1229.        (final.c) may indicate a move from the LSW of a long to an int
  1230.        in the same accumulator. */
  1231.  
  1232.     return "";
  1233.     }
  1234.     
  1235.     switch ( which_alternative )
  1236.     {
  1237.     case 0:
  1238.     if ( MEM_IN_STRUCT_P ( operands[0] ) || 
  1239.         MEM_IN_STRUCT_P ( operands[1] ))
  1240.     {
  1241.         return "move    %1,%0";
  1242.     }
  1243.     else
  1244.     {
  1245.         return "tfr    %1,%0";
  1246.     }
  1247.  
  1248.     case 1:
  1249.     return "move    %e1,%0";
  1250.     
  1251.     case 2:
  1252.     if ( PLUS == GET_CODE ( XEXP ( operands[0], 0 )))
  1253.     {
  1254.         if ( REG == GET_CODE ( XEXP ( XEXP ( operands[0], 0 ), 0 )))
  1255.         {
  1256.         operands[2] = XEXP ( XEXP ( operands[0], 0 ), 0 );
  1257.         operands[3] = XEXP ( XEXP ( operands[0], 0 ), 1 );
  1258.         }
  1259.         else
  1260.         {
  1261.         operands[2] = XEXP ( XEXP ( operands[0], 0 ), 1 );
  1262.         operands[3] = XEXP ( XEXP ( operands[0], 0 ), 0 );
  1263.         }
  1264.         
  1265.         if ( CONST_INT != GET_CODE ( operands[3] ))
  1266.         {
  1267.         if ( load_n_reg_p ( operands[2], operands[3] ))
  1268.         {
  1269.             RETURN_DSP ( "move    #%p3,%j2\n\tmove    %e1,@:(%2+%j2)" );
  1270.         }
  1271.         else
  1272.         {
  1273.             RETURN_DSP ( "move    %e1,@:(%2+%j2)" );
  1274.         }
  1275.         }
  1276.         
  1277.         switch ( INTVAL ( operands[3] ))
  1278.         {
  1279.         case 0:
  1280.         RETURN_DSP ( "move    %e1,@:(%2)" );
  1281.             
  1282.         case 1:
  1283.         if ( REGNO ( operands[2] ) != REGNO ( operands[1] ))
  1284.         {
  1285.             RETURN_DSP ( "move    (%2)+\n\tmove    %e1,@:(%2)-" );
  1286.         }
  1287.             
  1288.         case -1:
  1289.         if ( REGNO ( operands[2] ) != REGNO ( operands[1] ))
  1290.         {
  1291.             RETURN_DSP ( "move    (%2)-\n\tmove    %e1,@:(%2)+" );
  1292.         }
  1293.         
  1294.         default:
  1295.         if ( load_n_reg_p ( operands[2], operands[3] ))
  1296.         {
  1297.             RETURN_DSP ( "move    #%p3,%j2\n\tmove    %e1,@:(%2+%j2)" );
  1298.         }
  1299.         else
  1300.         {
  1301.             RETURN_DSP ( "move    %e1,@:(%2+%j2)" );
  1302.         }
  1303.         }
  1304.     }
  1305.     else
  1306.     {
  1307.         return "move    %e1,%f0";
  1308.     }
  1309.     
  1310.     case 3:
  1311.     if ( PLUS == GET_CODE ( XEXP ( operands[1], 0 )))
  1312.     {
  1313.         if ( REG == GET_CODE ( XEXP ( XEXP ( operands[1], 0 ), 0 )))
  1314.         {
  1315.         operands[2] = XEXP ( XEXP ( operands[1], 0 ), 0 );
  1316.         operands[3] = XEXP ( XEXP ( operands[1], 0 ), 1 );
  1317.         }
  1318.         else
  1319.         {
  1320.         operands[2] = XEXP ( XEXP ( operands[1], 0 ), 1 );
  1321.         operands[3] = XEXP ( XEXP ( operands[1], 0 ), 0 );
  1322.         }
  1323.         
  1324.         if ( CONST_INT != GET_CODE ( operands[3] ))
  1325.         {
  1326.         if ( load_n_reg_p ( operands[2], operands[3] ))
  1327.         {
  1328.             RETURN_DSP ( "move    #%p3,%j2\n\tmove    @:(%2+%j2),%0" );
  1329.         }
  1330.         else
  1331.         {
  1332.             RETURN_DSP ( "move    @:(%2+%j2),%0" );
  1333.         }
  1334.         }
  1335.         
  1336.         switch ( INTVAL ( operands[3] ))
  1337.         {
  1338.         case 0:
  1339.         RETURN_DSP ( "move    @:(%2),%0" );
  1340.             
  1341.         case 1:
  1342.         if ( REGNO ( operands[0] ) != REGNO ( operands[2] ))
  1343.         {
  1344.             RETURN_DSP ( "move    (%2)+\n\tmove    @:(%2)-,%0" );
  1345.         }
  1346.             
  1347.         case -1:
  1348.         if ( REGNO ( operands[0] ) != REGNO ( operands[2] ))
  1349.         {
  1350.             RETURN_DSP ( "move    (%2)-\n\tmove    @:(%2)+,%0" );
  1351.         }
  1352.         
  1353.         default:
  1354.         if ( load_n_reg_p ( operands[2], operands[3] ))
  1355.         {
  1356.             RETURN_DSP ( "move    #%p3,%j2\n\tmove    @:(%2+%j2),%0" );
  1357.         }
  1358.         else
  1359.         {
  1360.             RETURN_DSP ( "move    @:(%2+%j2),%0" );
  1361.         }
  1362.         }
  1363.     }
  1364.     else
  1365.     {
  1366.         return "move    %f1,%0";
  1367.     }
  1368.     
  1369.     case 4:
  1370.     if ( 0 == INTVAL ( operands[1] ))
  1371.     {
  1372.         if ( DST_REGS == REGNO_REG_CLASS ( REGNO ( operands[0] )))
  1373.         {
  1374.         return "clr    %0";
  1375.         }
  1376.         else
  1377.         {
  1378.         return "move    #%c1,%0";
  1379.         }
  1380.     }
  1381.     else
  1382.     {
  1383.         return "move    #>%q1,%0";
  1384.     }
  1385.     }
  1386. }
  1387.  
  1388. char*
  1389. move_doubleword ( is_float_p, operands )
  1390.     int is_float_p;
  1391.     rtx *operands;
  1392. {
  1393.     extern char mem_space;
  1394.     extern union real_extract adjusted_dval;
  1395.  
  1396.     if ( rtx_equal_p ( operands[0], operands[1] ))
  1397.     {
  1398.     return "";
  1399.     }
  1400.     
  1401.     switch ( which_alternative )
  1402.     {
  1403.     case 0:
  1404.     if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
  1405.     {
  1406.         if ( MEM_IN_STRUCT_P ( operands[0] )  ||
  1407.         MEM_IN_STRUCT_P ( operands[1] ))
  1408.         {
  1409.         return "move    %g1,%0\n\tmove    %1,%h0";
  1410.         }
  1411.         else
  1412.         {
  1413.         return "tfr    %g1,%0\n\tmove    %1,%h0";
  1414.         }
  1415.     }
  1416.     else
  1417.     {
  1418.         if ( MEM_IN_STRUCT_P ( operands[0] )  ||
  1419.         MEM_IN_STRUCT_P ( operands[1] ))
  1420.         {
  1421.         return "move    %1,%0";
  1422.         }
  1423.         else
  1424.         {
  1425.         return "tfr    %1,%0";
  1426.         }
  1427.     }
  1428.  
  1429.     case 1:
  1430.     if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
  1431.     {
  1432.         return "move    %g1,%g0\n\tmove    %1,%0";
  1433.     }
  1434.     else
  1435.     {
  1436.         return "move    %e1,%g0\n\tmove    %h1,%0";
  1437.     }
  1438.  
  1439.     case 2:
  1440.     if ( 'l' == memory_model )
  1441.     {
  1442.         if ( PLUS == GET_CODE ( XEXP ( operands[0], 0 )))
  1443.         {
  1444.         if ( REG == GET_CODE ( XEXP ( XEXP ( operands[0], 0 ), 0 )))
  1445.         {
  1446.             operands[2] = XEXP ( XEXP ( operands[0], 0 ), 0 );
  1447.             operands[3] = XEXP ( XEXP ( operands[0], 0 ), 1 );
  1448.         }
  1449.         else
  1450.         {
  1451.             operands[2] = XEXP ( XEXP ( operands[0], 0 ), 1 );
  1452.             operands[3] = XEXP ( XEXP ( operands[0], 0 ), 0 );
  1453.         }
  1454.         
  1455.         if ( CONST_INT != GET_CODE ( operands[3] ))
  1456.         {
  1457.             if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
  1458.             {
  1459.             if ( load_n_reg_p ( operands[2], operands[3] ))
  1460.             {
  1461.                 return "move    #%p3,%j2\n\tmove    %m1,l:(%2+%j2)";
  1462.             }
  1463.             else
  1464.             {
  1465.                 return "move    %m1,l:(%2+%j2)";
  1466.             }
  1467.             }
  1468.             else
  1469.             {
  1470.             if ( load_n_reg_p ( operands[2], operands[3] ))
  1471.             {
  1472.                 return "move    #%p3,%j2\n\tmove    %o1,l:(%2+%j2)";
  1473.             }
  1474.             else
  1475.             {
  1476.                 return "move    %o1,l:(%2+%j2)";
  1477.             }
  1478.             }
  1479.         }
  1480.         
  1481.         switch ( INTVAL ( operands[3] ))
  1482.         {
  1483.         case 0:
  1484.             if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
  1485.             {
  1486.             return "move    %m1,l:(%2)";
  1487.             }
  1488.             else
  1489.             {
  1490.             return "move    %o1,l:(%2)";
  1491.             }
  1492.             
  1493.         case 1:
  1494.             if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
  1495.             {
  1496.             return "move    (%2)+\n\tmove    %m1,l:(%2)-";
  1497.             }
  1498.             else
  1499.             {
  1500.             return "move    (%2)+\n\tmove    %o1,l:(%2)-";
  1501.             }
  1502.             
  1503.         case -1:
  1504.             if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
  1505.             {
  1506.             return "move    (%2)-\n\tmove    %m1,l:(%2)+";
  1507.             }
  1508.             else
  1509.             {
  1510.             return "move    (%2)-\n\tmove    %o1,l:(%2)+";
  1511.             }
  1512.             
  1513.         default:
  1514.             if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
  1515.             {
  1516.             if ( load_n_reg_p ( operands[2], operands[3] ))
  1517.             {
  1518.                 return "move    #%p3,%j2\n\tmove    %m1,l:(%2+%j2)";
  1519.             }
  1520.             else
  1521.             {
  1522.                 return "move    %m1,l:(%2+%j2)";
  1523.             }
  1524.             }
  1525.             else
  1526.             {
  1527.             if ( load_n_reg_p ( operands[2], operands[3] ))
  1528.             {
  1529.                 return "move    #%p3,%j2\n\tmove    %o1,l:(%2+%j2)";
  1530.             }
  1531.             else
  1532.             {
  1533.                 return "move    %o1,l:(%2+%j2)";
  1534.             }
  1535.             }
  1536.         }
  1537.         }
  1538.         else
  1539.         {
  1540.         if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
  1541.         {
  1542.             return "move    %m1,%f0";
  1543.         }
  1544.         else
  1545.         {
  1546.             return "move    %o1,%f0";
  1547.         }
  1548.         }
  1549.     }
  1550.     else /* memory_model is x or y. */
  1551.     {
  1552.         if ( PLUS == GET_CODE ( XEXP ( operands[0], 0 )))
  1553.         {
  1554.         if ( REG == GET_CODE ( XEXP ( XEXP ( operands[0], 0 ), 0 )))
  1555.         {
  1556.             operands[2] = XEXP ( XEXP ( operands[0], 0 ), 0 );
  1557.             operands[3] = XEXP ( XEXP ( operands[0], 0 ), 1 );
  1558.         }
  1559.         else
  1560.         {
  1561.             operands[2] = XEXP ( XEXP ( operands[0], 0 ), 1 );
  1562.             operands[3] = XEXP ( XEXP ( operands[0], 0 ), 0 );
  1563.         }
  1564.         
  1565.         if ( CONST_INT != GET_CODE ( operands[3] ))
  1566.         {
  1567.             if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
  1568.             {
  1569.             if ( load_n_reg_p ( operands[2], operands[3] ))
  1570.             {
  1571.                 RETURN_DSP ( "move    #%p3,%j2\n\tmove    (%2)+\n\tmove    (%2)+%j2\n\tmove    %g1,@:(%2)-\n\tmove    %1,@:(%2)-%j2" );
  1572.             }
  1573.             else
  1574.             {
  1575.                 RETURN_DSP ( "move    (%2)+\n\tmove    (%2)+%j2\n\tmove    %g1,@:(%2)-\n\tmove    %1,@:(%2)-%j2" );
  1576.             }
  1577.             }
  1578.             else
  1579.             {
  1580.             if ( load_n_reg_p ( operands[2], operands[3] ))
  1581.             {
  1582.                 RETURN_DSP ( "move    #%p3,%j2\n\tmove    (%2)+\n\tmove    (%2)+%j2\n\tmove    %e1,@:(%2)-\n\tmove    %h1,@:(%2)-%j2" );
  1583.             }
  1584.             else
  1585.             {
  1586.                 RETURN_DSP ( "move    (%2)+\n\tmove    (%2)+%j2\n\tmove    %e1,@:(%2)-\n\tmove    %h1,@:(%2)-%j2" );
  1587.             }
  1588.             }
  1589.         }
  1590.         
  1591.         switch ( INTVAL ( operands[3] ))
  1592.         {
  1593.         case 0:
  1594.             if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
  1595.             {
  1596.             RETURN_DSP ( "move    %1,@:(%2)+\n\tmove    %g1,@:(%2)-" );
  1597.             }
  1598.             else
  1599.             {
  1600.             RETURN_DSP ( "move    %h1,@:(%2)+\n\tmove    %e1,@:(%2)-" );
  1601.             }
  1602.             
  1603.         case 1:
  1604.             if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
  1605.             {
  1606.             RETURN_DSP ( "move    (%2)+\n\tmove    %1,@:(%2)+\n\tmove    %g1,@:(%2)-\n\tmove    (%2)-" );
  1607.             }
  1608.             else
  1609.             {
  1610.             RETURN_DSP ( "move    (%2)+\n\tmove    %h1,@:(%2)+\n\tmove    %e1,@:(%2)-\n\tmove    (%2)-" );
  1611.             }
  1612.             
  1613.         case -1:
  1614.             if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
  1615.             {
  1616.             RETURN_DSP ( "move    (%2)-\n\tmove    %g1,@:(%2)-\n\tmove    %1,@:(%2)+\n\tmove    (%2)+" );
  1617.             }
  1618.             else
  1619.             {
  1620.             RETURN_DSP ( "move    (%2)-\n\tmove    %e1,@:(%2)-\n\tmove    %h1,@:(%2)+\n\tmove    (%2)+" );
  1621.             }
  1622.             
  1623.         default:
  1624.             if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
  1625.             {
  1626.             if ( load_n_reg_p ( operands[2], operands[3] ))
  1627.             {
  1628.                 RETURN_DSP ( "move    #%p3,%j2\n\tmove    (%2)+\n\tmove    (%2)+%j2\n\tmove    %g1,@:(%2)-\n\tmove    %1,@:(%2)-%j2" );
  1629.             }
  1630.             else
  1631.             {
  1632.                 RETURN_DSP ( "move    (%2)+\n\tmove    (%2)+%j2\n\tmove    %g1,@:(%2)-\n\tmove    %1,@:(%2)-%j2" );
  1633.             }
  1634.             }
  1635.             else
  1636.             {
  1637.             if ( load_n_reg_p ( operands[2], operands[3] ))
  1638.             {
  1639.                 RETURN_DSP ( "move    #%p3,%j2\n\tmove    (%2)+\n\tmove    (%2)+%j2\n\tmove    %e1,@:(%2)-\n\tmove    %h1,@:(%2)-%j2" );
  1640.             }
  1641.             else
  1642.             {
  1643.                 RETURN_DSP ( "move    (%2)+\n\tmove    (%2)+%j2\n\tmove    %e1,@:(%2)-\n\tmove    %h1,@:(%2)-%j2" );
  1644.             }
  1645.             }
  1646.         }
  1647.         }
  1648.         else if ( POST_INC == GET_CODE ( XEXP ( operands[0], 0 )))
  1649.         {
  1650.         operands[2] = XEXP ( XEXP ( operands[0], 0 ), 0 );
  1651.         
  1652.         if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
  1653.         {
  1654.             RETURN_DSP ( "move    %1,@:(%2)+\n\tmove    %g1,@:(%2)+" );
  1655.         }
  1656.         else
  1657.         {
  1658.             RETURN_DSP ( "move    %h1,@:(%2)+\n\tmove    %e1,@:(%2)+" );
  1659.         }
  1660.         }
  1661.         else if ( POST_DEC == GET_CODE ( XEXP ( operands[0], 0 )))
  1662.         {
  1663.         operands[2] = XEXP ( XEXP ( operands[0], 0 ), 0 );
  1664.         
  1665.         if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
  1666.         {
  1667.             if ( load_n_reg_p ( operands[2], 
  1668.                        gen_rtx ( CONST_INT, VOIDmode, 3 )))
  1669.             {
  1670.             RETURN_DSP ( "move    #3,%j2\n\tmove    %1,@:(%2)+\n\tmove    %g1,@:(%2)-%j2" );
  1671.             }
  1672.             else
  1673.             {
  1674.             RETURN_DSP ( "move    %1,@:(%2)+\n\tmove    %g1,@:(%2)-%j2" );
  1675.             }
  1676.         }
  1677.         else
  1678.         {
  1679.             if ( load_n_reg_p ( operands[2], 
  1680.                        gen_rtx ( CONST_INT, VOIDmode, 3 )))
  1681.             {
  1682.             RETURN_DSP ( "move    #3,%j2\n\tmove    %h1,@:(%2)+\n\tmove    %e1,@:(%2)-%j2" );
  1683.             }
  1684.             else
  1685.             {
  1686.             RETURN_DSP ( "move    %h1,@:(%2)+\n\tmove    %e1,@:(%2)-%j2" );
  1687.             }
  1688.         }
  1689.         }
  1690.         else if ( REG == GET_CODE ( XEXP ( operands[0], 0 )))
  1691.         {
  1692.         operands[2] = XEXP ( operands[0], 0 );
  1693.         
  1694.         if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
  1695.         {
  1696.             RETURN_DSP ( "move    %1,@:(%2)+\n\tmove    %g1,@:(%2)-" );
  1697.         }
  1698.         else
  1699.         {
  1700.             RETURN_DSP ( "move    %h1,@:(%2)+\n\tmove    %e1,@:(%2)-" );
  1701.         }
  1702.         }
  1703.         else
  1704.         {
  1705.         if ( IS_SRC_OR_MPY_P ( REGNO ( operands[1] )))
  1706.         {
  1707.             return "move    %1,%f0\n\tmove    %g1,%f0+1";
  1708.         }
  1709.         else
  1710.         {
  1711.             return "move    %h1,%f0\n\tmove    %e1,%f0+1";
  1712.         }
  1713.         }
  1714.     }
  1715.     
  1716.     case 3:
  1717.     if ( 'l' == memory_model )
  1718.     {
  1719.         if ( PLUS == GET_CODE ( XEXP ( operands[1], 0 )))
  1720.         {
  1721.         if ( REG == GET_CODE ( XEXP ( XEXP ( operands[1], 0 ), 0 )))
  1722.         {
  1723.             operands[2] = XEXP ( XEXP ( operands[1], 0 ), 0 );
  1724.             operands[3] = XEXP ( XEXP ( operands[1], 0 ), 1 );
  1725.         }
  1726.         else
  1727.         {
  1728.             operands[2] = XEXP ( XEXP ( operands[1], 0 ), 1 );
  1729.             operands[3] = XEXP ( XEXP ( operands[1], 0 ), 0 );
  1730.         }
  1731.         
  1732.         if ( CONST_INT != GET_CODE ( operands[3] ))
  1733.         {
  1734.             if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
  1735.             {
  1736.             if ( load_n_reg_p ( operands[2], operands[3] ))
  1737.             {
  1738.                 return "move    #%p3,%j2\n\tmove    l:(%2+%j2),%m0";
  1739.             }
  1740.             else
  1741.             {
  1742.                 return "move    l:(%2+%j2),%m0";
  1743.             }
  1744.             }
  1745.             else
  1746.             {
  1747.             if ( load_n_reg_p ( operands[2], operands[3] ))
  1748.             {
  1749.                 return "move    #%p3,%j2\n\tmove    l:(%2+%j2),%0";
  1750.             }
  1751.             else
  1752.             {
  1753.                 return "move    l:(%2+%j2),%0";
  1754.             }
  1755.             }
  1756.         }
  1757.         
  1758.         switch ( INTVAL ( operands[3] ))
  1759.         {
  1760.         case 0:
  1761.             if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
  1762.             {
  1763.             return "move    l:(%2),%m0";
  1764.             }
  1765.             else
  1766.             {
  1767.             return "move    l:(%2),%0";
  1768.             }
  1769.             
  1770.         case 1:
  1771.             if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
  1772.             {
  1773.             return "move    (%2)+\n\tmove    l:(%2)-,%m0";
  1774.             }
  1775.             else
  1776.             {
  1777.             return "move    (%2)+\n\tmove    l:(%2)-,%0";
  1778.             }
  1779.             
  1780.         case -1:
  1781.             if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
  1782.             {
  1783.             return "move    (%2)-\n\tmove    l:(%2)+,%m0";
  1784.             }
  1785.             else
  1786.             {
  1787.             return "move    (%2)-\n\tmove    l:(%2)+,%0";
  1788.             }
  1789.             
  1790.         default:
  1791.             if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
  1792.             {
  1793.             if ( load_n_reg_p ( operands[2], operands[3] ))
  1794.             {
  1795.                 return "move    #%p3,%j2\n\tmove    l:(%2+%j2),%m0";
  1796.             }
  1797.             else
  1798.             {
  1799.                 return "move    l:(%2+%j2),%m0";
  1800.             }
  1801.             }
  1802.             else
  1803.             {
  1804.             if ( load_n_reg_p ( operands[2], operands[3] ))
  1805.             {
  1806.                 return "move    #%p3,%j2\n\tmove    l:(%2+%j2),%0";
  1807.             }
  1808.             else
  1809.             {
  1810.                 return "move    l:(%2+%j2),%0";
  1811.             }
  1812.             }
  1813.         }
  1814.         }
  1815.         else
  1816.         {
  1817.         if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
  1818.         {
  1819.             return "move    %f1,%m0";
  1820.         }
  1821.         else
  1822.         {
  1823.             return "move    %f1,%0";
  1824.         }
  1825.         }
  1826.     }
  1827.     else /* memory_model is x or y */
  1828.     {
  1829.         if ( PLUS == GET_CODE ( XEXP ( operands[1], 0 )))
  1830.         {
  1831.         if ( REG == GET_CODE ( XEXP ( XEXP ( operands[1], 0 ), 0 )))
  1832.         {
  1833.             operands[2] = XEXP ( XEXP ( operands[1], 0 ), 0 );
  1834.             operands[3] = XEXP ( XEXP ( operands[1], 0 ), 1 );
  1835.         }
  1836.         else
  1837.         {
  1838.             operands[2] = XEXP ( XEXP ( operands[1], 0 ), 1 );
  1839.             operands[3] = XEXP ( XEXP ( operands[1], 0 ), 0 );
  1840.         }
  1841.         
  1842.         if ( CONST_INT != GET_CODE ( operands[3] ))
  1843.         {
  1844.             if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
  1845.             {
  1846.             if ( load_n_reg_p ( operands[2], operands[3] ))
  1847.             {
  1848.                 RETURN_DSP ( "move    #%p3,%j2\n\tmove    (%2)+\n\tmove    (%2)+%j2\n\tmove    @:(%2)-,%g0\n\tmove    @:(%2)-%j2,%0" );
  1849.             }
  1850.             else
  1851.             {
  1852.                 RETURN_DSP ( "move    (%2)+\n\tmove    (%2)+%j2\n\tmove    @:(%2)-,%g0\n\tmove    @:(%2)-%j2,%0" );
  1853.             }
  1854.             }
  1855.             else
  1856.             {
  1857.             if ( load_n_reg_p ( operands[2], operands[3] ))
  1858.             {
  1859.                 RETURN_DSP ( "move    #%p3,%j2\n\tmove    (%2)+\n\tmove    (%2)+%j2\n\tmove    @:(%2)-,%0\n\tmove    @:(%2)-%j2,%h0" );
  1860.             }
  1861.             else
  1862.             {
  1863.                 RETURN_DSP ( "move    (%2)+\n\tmove    (%2)+%j2\n\tmove    @:(%2)-,%0\n\tmove    @:(%2)-%j2,%h0" );
  1864.             }
  1865.             }
  1866.         }
  1867.         
  1868.         switch ( INTVAL ( operands[3] ))
  1869.         {
  1870.         case 0:
  1871.             if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
  1872.             {
  1873.             RETURN_DSP ( "move    (%2)+\n\tmove    @:(%2)-,%g0\n\tmove    @:(%2),%0" );
  1874.             }
  1875.             else
  1876.             {
  1877.             RETURN_DSP ( "move    (%2)+\n\tmove    @:(%2)-,%0\n\tmove    @:(%2),%h0" );
  1878.             }
  1879.             
  1880.         case 1:
  1881.             if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
  1882.             {
  1883.             RETURN_DSP ( "move    (%2)+\n\tmove    (%2)+\n\tmove    @:(%2)-,%g0\n\tmove    @:(%2)-,%0" );
  1884.             }
  1885.             else
  1886.             {
  1887.             RETURN_DSP ( "move    (%2)+\n\tmove    (%2)+\n\tmove    @:(%2)-,%0\n\tmove    @:(%2)-,%h0" );
  1888.             }
  1889.             
  1890.         case -1:
  1891.             if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
  1892.             {
  1893.             RETURN_DSP ( "move    (%2)-\n\tmove    @:(%2)-,%g0\n\tmove    @:(%2)+,%0\n\tmove    (%2)+" );
  1894.             }
  1895.             else
  1896.             {
  1897.             RETURN_DSP ( "move    (%2)-\n\tmove    @:(%2)-,%0\n\tmove    @:(%2)+,%h0\n\tmove    (%2)+" );
  1898.             }
  1899.             
  1900.         default:
  1901.             if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
  1902.             {
  1903.             if ( load_n_reg_p ( operands[2], operands[3] ))
  1904.             {
  1905.                 RETURN_DSP ( "move    #%p3,%j2\n\tmove    (%2)+\n\tmove    (%2)+%j2\n\tmove    @:(%2)-,%g0\n\tmove    @:(%2)-%j2,%0" );
  1906.             }
  1907.             else
  1908.             {
  1909.                 RETURN_DSP ( "move    (%2)+\n\tmove    (%2)+%j2\n\tmove    @:(%2)-,%g0\n\tmove    @:(%2)-%j2,%0" );
  1910.             }
  1911.             }
  1912.             else
  1913.             {
  1914.             if ( load_n_reg_p ( operands[2], operands[3] ))
  1915.             {
  1916.                 RETURN_DSP ( "move    #%p3,%j2\n\tmove    (%2)+\n\tmove    (%2)+%j2\n\tmove    @:(%2)-,%0\n\tmove    @:(%2)-%j2,%h0" );
  1917.             }
  1918.             else
  1919.             {
  1920.                 RETURN_DSP ( "move    (%2)+\n\tmove    (%2)+%j2\n\tmove    @:(%2)-,%0\n\tmove    @:(%2)-%j2,%h0" );
  1921.             }
  1922.             }
  1923.         }
  1924.         }
  1925.         else if ( POST_INC == GET_CODE ( XEXP ( operands[1], 0 )))
  1926.         {
  1927.         operands[2] = XEXP ( XEXP ( operands[1], 0 ), 0 );
  1928.         
  1929.         if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
  1930.         {
  1931.             if ( load_n_reg_p ( operands[2], 
  1932.                        gen_rtx ( CONST_INT, VOIDmode, 2 )))
  1933.             {
  1934.             RETURN_DSP ( "move    #2,%j2\n\tmove    (%2)+\n\tmove    @:(%2)-,%g0\n\tmove    @:(%2)+%j2,%0" );
  1935.             }
  1936.             else
  1937.             {
  1938.             RETURN_DSP ( "move    (%2)+\n\tmove    @:(%2)-,%g0\n\tmove    @:(%2)+%j2,%0" );
  1939.             }
  1940.         }
  1941.         else
  1942.         {
  1943.             if ( load_n_reg_p ( operands[2], 
  1944.                        gen_rtx ( CONST_INT, VOIDmode, 2 )))
  1945.             {
  1946.             RETURN_DSP ( "move    #2,%j2\n\tmove    (%2)+\n\tmove    @:(%2)-,%0\n\tmove    @:(%2)+%j2,%h0" );
  1947.             }
  1948.             else
  1949.             {
  1950.             RETURN_DSP ( "move    (%2)+\n\tmove    @:(%2)-,%0\n\tmove    @:(%2)+%j2,%h0" );
  1951.             }
  1952.         }
  1953.         }
  1954.         else if ( POST_DEC == GET_CODE ( XEXP ( operands[1], 0 )))
  1955.         {
  1956.         operands[2] = XEXP ( XEXP ( operands[1], 0 ), 0 );
  1957.         
  1958.         if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
  1959.         {
  1960.             if ( load_n_reg_p ( operands[2], 
  1961.                        gen_rtx ( CONST_INT, VOIDmode, 2 )))
  1962.             {
  1963.             RETURN_DSP ( "move    #2,%j2\n\tmove    (%2)+\n\tmove    @:(%2)-,%g0\n\tmove    @:(%2)-%j2,%0" );
  1964.             }
  1965.             else
  1966.             {
  1967.             RETURN_DSP ( "move    (%2)+\n\tmove    @:(%2)-,%g0\n\tmove    @:(%2)-%j2,%0" );
  1968.             }
  1969.         }
  1970.         else
  1971.         {
  1972.             if ( load_n_reg_p ( operands[2], 
  1973.                        gen_rtx ( CONST_INT, VOIDmode, 2 )))
  1974.             {
  1975.             RETURN_DSP ( "move    #2,%j2\n\tmove    (%2)+\n\tmove    @:(%2)-,%0\n\tmove    @:(%2)-%j2,%h0" );
  1976.             }
  1977.             else
  1978.             {
  1979.             RETURN_DSP ( "move    (%2)+\n\tmove    @:(%2)-,%0\n\tmove    @:(%2)-%j2,%h0" );
  1980.             }
  1981.         }
  1982.         }
  1983.         else if ( REG == GET_CODE ( XEXP ( operands[1], 0 )))
  1984.         {
  1985.         operands[2] = XEXP ( operands[1], 0 );
  1986.         
  1987.         if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
  1988.         {
  1989.             RETURN_DSP ( "move    (%2)+\n\tmove    @:(%2)-,%g0\n\tmove    @:(%2),%0" );
  1990.         }
  1991.         else
  1992.         {
  1993.             RETURN_DSP ( "move    (%2)+\n\tmove    @:(%2)-,%0\n\tmove    @:(%2),%h0" );
  1994.         }
  1995.         }
  1996.         else
  1997.         {
  1998.         if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
  1999.         {
  2000.             return "move    %f1+1,%g0\n\tmove    %f1,%0";
  2001.         }
  2002.         else
  2003.         {
  2004.             return "move    %f1+1,%0\n\tmove    %f1,%h0";
  2005.         }
  2006.         }
  2007.     }
  2008.     
  2009.     case 4:
  2010.     if ( is_float_p )
  2011.     {
  2012.         dtok ( NULL, *(union real_extract*) 
  2013.           &CONST_DOUBLE_LOW ( operands[1] ));
  2014.     
  2015.         operands[2] =
  2016.         gen_rtx ( CONST_INT, VOIDmode, adjusted_dval.i[1] );
  2017.     
  2018.         operands[3] = 
  2019.         gen_rtx ( CONST_INT, VOIDmode, adjusted_dval.i[0] );
  2020.         
  2021.         if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
  2022.         {
  2023.         return "move    #>%q2,%g0\n\tmove    #>%q3,%0";
  2024.         }
  2025.         else
  2026.         {
  2027.         if ( 0 == INTVAL ( operands[3] ))
  2028.         {
  2029.             if ( 0 == INTVAL ( operands[2] ))
  2030.             {
  2031.             return "clr    %0";
  2032.             }
  2033.             else
  2034.             {
  2035.             return "move    #>%q2,%0";
  2036.             }
  2037.         }
  2038.         else
  2039.         {
  2040.             return "move    #>%q2,%0\n\tmove    #>%q3,%h0";
  2041.         }
  2042.         }
  2043.     }
  2044.     else /* not a floating constant. */
  2045.     {
  2046.         if ( CONST_INT == GET_CODE ( operands[1] ))
  2047.         {
  2048.         if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
  2049.         {
  2050.             if ( 0 == INTVAL ( operands[1] ))
  2051.             {
  2052.             return "move    #0,%g0\n\tmove    #%c1,%0";
  2053.             }
  2054.             else if ( 0 > INTVAL ( operands[1] ))
  2055.             {
  2056.             return "move    #-1,%g0\n\tmove    #>%q1,%0";
  2057.             }
  2058.             else
  2059.             {
  2060.             return "move    #0,%g0\n\tmove    #>%q1,%0";
  2061.             }
  2062.         }
  2063.         else
  2064.         {
  2065.             if ( 0 == INTVAL ( operands[1] ))
  2066.             {
  2067.             return "clr    %0";
  2068.             }
  2069.             else if ( 0 > INTVAL ( operands[1] ))
  2070.             {
  2071.             return "move    #-1,%0\n\tmove    #>%q1,%h0";
  2072.             }
  2073.             else
  2074.             {
  2075.             return "move    #0,%0\n\tmove    #>%q1,%h0";
  2076.             }
  2077.         }
  2078.         }
  2079.         
  2080.         operands[2] =
  2081.         gen_rtx ( CONST_INT, VOIDmode, 
  2082.              (( CONST_DOUBLE_LOW ( operands[1] ) >> 24 ) & 0x0000ff ) |
  2083.              (( CONST_DOUBLE_HIGH ( operands[1] ) << 8 ) & 0xffff00 ));
  2084.         operands[3] = 
  2085.         gen_rtx ( CONST_INT, VOIDmode,
  2086.              ( CONST_DOUBLE_LOW ( operands[1] ) & 0xffffff ));
  2087.         
  2088.         if ( IS_SRC_OR_MPY_P ( REGNO ( operands[0] )))
  2089.         {
  2090.         if ( rtx_equal_p ( operands[2], operands[3] ))
  2091.         {
  2092.             return "move    #>%q2,%g0\n\tmove    %g0,%0";
  2093.         }
  2094.         else
  2095.         {
  2096.             return "move    #>%q2,%g0\n\tmove    #>%q3,%0";
  2097.         }
  2098.         }
  2099.         else
  2100.         {
  2101.         if ( 0 == INTVAL ( operands[3] ))
  2102.         {
  2103.             if ( 0 == INTVAL ( operands[2] ))
  2104.             {
  2105.             return "clr    %0";
  2106.             }
  2107.             else
  2108.             {
  2109.             return "move    #>%q2,%0";
  2110.             }
  2111.         }
  2112.         else
  2113.         {
  2114.             if ( rtx_equal_p ( operands[2], operands[3] ))
  2115.             {
  2116.             return "move    #>%q2,%0\n\tmove    %0,%h0";
  2117.             }
  2118.             else
  2119.             {
  2120.             return "move    #>%q2,%0\n\tmove    #>%q3,%h0";
  2121.             }
  2122.         }
  2123.         }
  2124.     }
  2125.     }
  2126. }
  2127.  
  2128. char*
  2129. move_pointer ( operands )
  2130.     rtx *operands;
  2131. {
  2132.     extern char mem_space;
  2133.     
  2134.     if ( rtx_equal_p ( operands[0], operands[1] ))
  2135.     {
  2136.     return "";
  2137.     }
  2138.     
  2139.     switch ( which_alternative )
  2140.     {
  2141.     case 0:
  2142.     if ( MEM_IN_STRUCT_P ( operands[0] ) || 
  2143.         MEM_IN_STRUCT_P ( operands[1] ))
  2144.     {
  2145.         return "move    %1,%0";
  2146.     }
  2147.     else
  2148.     {
  2149.         return "tfr    %1,%0";
  2150.     }
  2151.  
  2152.     case 1:
  2153.     return "move    %e1,%0";
  2154.     
  2155.     case 2:
  2156.     if ( PLUS == GET_CODE ( XEXP ( operands[0], 0 )))
  2157.     {
  2158.         if ( REG == GET_CODE ( XEXP ( XEXP ( operands[0], 0 ), 0 )))
  2159.         {
  2160.         operands[2] = XEXP ( XEXP ( operands[0], 0 ), 0 );
  2161.         operands[3] = XEXP ( XEXP ( operands[0], 0 ), 1 );
  2162.         }
  2163.         else
  2164.         {
  2165.         operands[2] = XEXP ( XEXP ( operands[0], 0 ), 1 );
  2166.         operands[3] = XEXP ( XEXP ( operands[0], 0 ), 0 );
  2167.         }
  2168.         
  2169.         if ( CONST_INT != GET_CODE ( operands[3] ))
  2170.         {
  2171.         if ( load_n_reg_p ( operands[2], operands[3] ))
  2172.         {
  2173.             RETURN_DSP ( "move    #%p3,%j2\n\tmove    %e1,@:(%2+%j2)" );
  2174.         }
  2175.         else
  2176.         {
  2177.             RETURN_DSP ( "move    %e1,@:(%2+%j2)" );
  2178.         }
  2179.         }
  2180.         
  2181.         switch ( INTVAL ( operands[3] ))
  2182.         {
  2183.         case 0:
  2184.         RETURN_DSP ( "move    %e1,@:(%2)" );
  2185.             
  2186.         case 1:
  2187.         if ( REGNO ( operands[1] ) != REGNO ( operands[2] ))
  2188.         {
  2189.             RETURN_DSP ( "move    (%2)+\n\tmove    %e1,@:(%2)-" );
  2190.         }
  2191.             
  2192.         case -1:
  2193.         if ( REGNO ( operands[1] ) != REGNO ( operands[2] ))
  2194.         {
  2195.             RETURN_DSP ( "move    (%2)-\n\tmove    %e1,@:(%2)+" );
  2196.         }
  2197.         
  2198.         default:
  2199.         if ( load_n_reg_p ( operands[2], operands[3] ))
  2200.         {
  2201.             RETURN_DSP ( "move    #%p3,%j2\n\tmove    %e1,@:(%2+%j2)" );
  2202.         }
  2203.         else
  2204.         {
  2205.             RETURN_DSP ( "move    %e1,@:(%2+%j2)" );
  2206.         }
  2207.         }
  2208.     }
  2209.     else
  2210.     {
  2211.         return "move    %e1,%f0";
  2212.     }
  2213.     
  2214.     case 3:
  2215.     if ( PLUS == GET_CODE ( XEXP ( operands[1], 0 )))
  2216.     {
  2217.         if ( REG == GET_CODE ( XEXP ( XEXP ( operands[1], 0 ), 0 )))
  2218.         {
  2219.         operands[2] = XEXP ( XEXP ( operands[1], 0 ), 0 );
  2220.         operands[3] = XEXP ( XEXP ( operands[1], 0 ), 1 );
  2221.         }
  2222.         else
  2223.         {
  2224.         operands[2] = XEXP ( XEXP ( operands[1], 0 ), 1 );
  2225.         operands[3] = XEXP ( XEXP ( operands[1], 0 ), 0 );
  2226.         }
  2227.         
  2228.         if ( CONST_INT != GET_CODE ( operands[3] ))
  2229.         {
  2230.         if ( load_n_reg_p ( operands[2], operands[3] ))
  2231.         {
  2232.             RETURN_DSP ( "move    #%p3,%j2\n\tmove    @:(%2+%j2),%0" );
  2233.         }
  2234.         else
  2235.         {
  2236.             RETURN_DSP ( "move    @:(%2+%j2),%0" );
  2237.         }
  2238.         }
  2239.         
  2240.         switch ( INTVAL ( operands[3] ))
  2241.         {
  2242.         case 0:
  2243.         RETURN_DSP ( "move    @:(%2),%0" );
  2244.             
  2245.         case 1:
  2246.         if ( REGNO ( operands[0] ) != REGNO ( operands[2] ))
  2247.         {
  2248.             RETURN_DSP ( "move    (%2)+\n\tmove    @:(%2)-,%0" );
  2249.         }
  2250.             
  2251.         case -1:
  2252.         if ( REGNO ( operands[0] ) != REGNO ( operands[2] ))
  2253.         {
  2254.             RETURN_DSP ( "move    (%2)-\n\tmove    @:(%2)+,%0" );
  2255.         }
  2256.         
  2257.         default:
  2258.         if ( load_n_reg_p ( operands[2], operands[3] ))
  2259.         {
  2260.             RETURN_DSP ( "move    #%p3,%j2\n\tmove    @:(%2+%j2),%0" );
  2261.         }
  2262.         else
  2263.         {
  2264.             RETURN_DSP ( "move    @:(%2+%j2),%0" );
  2265.         }
  2266.         }
  2267.     }
  2268.     else
  2269.     {
  2270.         return "move    %f1,%0";
  2271.     }
  2272.     
  2273.     case 4:
  2274.     if ( 0 == INTVAL ( operands[1] ) ||
  2275.         ADDR_REGS == REGNO_REG_CLASS ( REGNO ( operands[0] )))
  2276.     {
  2277.         if ( DST_REGS == REGNO_REG_CLASS ( REGNO ( operands[0] )))
  2278.         {
  2279.         return "clr    %0";
  2280.         }
  2281.         else
  2282.         {
  2283.         return "move    #%c1,%0";
  2284.         }
  2285.     }
  2286.     else
  2287.     {
  2288.         return "move    #>%c1,%0";
  2289.     }
  2290.     }
  2291. }
  2292.  
  2293. #if 0
  2294. int
  2295. local_constant_address_p ( x )
  2296.     rtx x;
  2297. {
  2298.     static int found_label_or_symbol_p ( );
  2299.     
  2300.     switch ( GET_CODE ( x ))
  2301.     {
  2302.     case LABEL_REF:
  2303.     case SYMBOL_REF:
  2304.     return 1;
  2305.  
  2306.     case CONST:
  2307.     return found_label_or_symbol_p ( XEXP ( x, 0 ));
  2308.  
  2309.     default:
  2310.     return 0;
  2311.     }
  2312. }
  2313.  
  2314. static int
  2315. found_label_or_symbol_p ( x )
  2316.     rtx x;
  2317. {
  2318.     if (( LABEL_REF == GET_CODE ( x )) || ( SYMBOL_REF == GET_CODE ( x )))
  2319.     {
  2320.     return 1;
  2321.     }
  2322.     else
  2323.     { 
  2324.     char *p, *fmt = GET_RTX_FORMAT ( GET_CODE ( x ));
  2325.     
  2326.     p = fmt;
  2327.  
  2328.     while ( 'e' == *p )
  2329.     {
  2330.         if ( found_label_or_symbol_p ( XEXP ( x, p - fmt )))
  2331.         {
  2332.         return 1;
  2333.         }
  2334.         ++ p;
  2335.     }
  2336.     }
  2337.     return 0;
  2338. }
  2339. #endif
  2340.  
  2341. /* the following is a lot of bullshit to ensure that constants in the 
  2342.    assembly output *in no way* ever assume that the assembler will discard
  2343.    the carry from arithmetic operations on constants. */
  2344.  
  2345. static rtx ensure_signed_pointer_offsets ( );
  2346. static rtx ensure_signed_int_offsets ( );
  2347. static int find_symbol ( );
  2348.  
  2349. rtx
  2350. ensure_pointer_result_size ( x )
  2351.     rtx x;
  2352. {
  2353.     int mask = (~((-1) << POINTER_SIZE ));
  2354.     
  2355.     if ( CONST_INT == GET_CODE ( x ))
  2356.     {
  2357.     INTVAL ( x ) &= mask;
  2358.     }
  2359.     else if ( find_symbol ( x ))
  2360.     {
  2361.     x = ensure_signed_pointer_offsets ( x );
  2362.     }
  2363.     else
  2364.     {
  2365.     char *p, *fmt = GET_RTX_FORMAT ( GET_CODE ( x ));
  2366.     
  2367.     p = fmt;
  2368.     
  2369.     while ( '\0' != ( *p ))
  2370.     {
  2371.         if ( 'e' == ( *p ))
  2372.         {
  2373.         XEXP ( x, p - fmt ) =
  2374.             ensure_pointer_result_size ( XEXP ( x, p - fmt ));
  2375.         }
  2376.         ++ p;
  2377.     }
  2378.     }
  2379.     return x;
  2380. }
  2381.  
  2382. rtx
  2383. ensure_integer_result_size ( x )
  2384.     rtx x;
  2385. {
  2386.     int mask = (~((-1) << BITS_PER_UNIT ));
  2387.  
  2388.     if ( CONST_INT == GET_CODE ( x ))
  2389.     {
  2390.     INTVAL ( x ) &= mask;
  2391.     }
  2392.     else if ( find_symbol ( x ))
  2393.     {
  2394.     x = ensure_signed_int_offsets ( x );
  2395.     }
  2396.     else
  2397.     {
  2398.     char *p, *fmt = GET_RTX_FORMAT ( GET_CODE ( x ));
  2399.     
  2400.     p = fmt;
  2401.     
  2402.     while ( '\0' != ( *p ))
  2403.     {
  2404.         if ( 'e' == ( *p ))
  2405.         {
  2406.         XEXP ( x, p - fmt ) = 
  2407.             ensure_integer_result_size ( XEXP ( x, p - fmt ));
  2408.         }
  2409.         ++ p;
  2410.     }
  2411.     }
  2412.     return x;
  2413. }
  2414.  
  2415. static rtx
  2416. ensure_signed_pointer_offsets ( x )
  2417.     rtx x;
  2418. {
  2419.     if ( CONST_INT == GET_CODE ( x ))
  2420.     {
  2421.      INTVAL ( x ) = (( INTVAL ( x ) << ( HOST_BITS_PER_INT - POINTER_SIZE ))
  2422.              >> ( HOST_BITS_PER_INT - POINTER_SIZE ));
  2423.     }
  2424.     else
  2425.     {
  2426.     char *p, *fmt = GET_RTX_FORMAT ( GET_CODE ( x ));
  2427.     
  2428.     p = fmt;
  2429.     
  2430.     while ( '\0' != ( *p ))
  2431.     {
  2432.         if ( 'e' == ( *p ))
  2433.         {
  2434.         XEXP ( x, p - fmt ) =
  2435.             ensure_signed_pointer_offsets ( XEXP ( x, p - fmt ));
  2436.         }
  2437.         ++ p;
  2438.     }
  2439.     }
  2440.     return x;
  2441. }
  2442.  
  2443. static rtx
  2444. ensure_signed_int_offsets ( x )
  2445.     rtx x;
  2446. {
  2447.     if ( CONST_INT == GET_CODE ( x ))
  2448.     {
  2449.      INTVAL ( x ) =(( INTVAL ( x ) << ( HOST_BITS_PER_INT - BITS_PER_UNIT ))
  2450.                >> ( HOST_BITS_PER_INT - BITS_PER_UNIT ));
  2451.     }
  2452.     else
  2453.     {
  2454.     char *p, *fmt = GET_RTX_FORMAT ( GET_CODE ( x ));
  2455.     
  2456.     p = fmt;
  2457.     
  2458.     while ( '\0' != ( *p ))
  2459.     {
  2460.         if ( 'e' == ( *p ))
  2461.         {
  2462.         XEXP ( x, p - fmt ) = 
  2463.             ensure_signed_int_offsets ( XEXP ( x, p - fmt ));
  2464.         }
  2465.         ++ p;
  2466.     }
  2467.     }
  2468.     return x;
  2469. }
  2470.  
  2471. static int
  2472. find_symbol ( x )
  2473.     rtx x;
  2474. {
  2475.     int found_symbol = 0;
  2476.     char *p, *fmt = GET_RTX_FORMAT ( GET_CODE ( x ));
  2477.  
  2478.     if ( SYMBOL_REF == GET_CODE ( x ))
  2479.     {
  2480.     return 1;
  2481.     }
  2482.     
  2483.     p = fmt;
  2484.     
  2485.     while ( '\0' != ( *p ))
  2486.     {
  2487.     if ( 'e' == ( *p ))
  2488.     {
  2489.         found_symbol |= find_symbol ( XEXP ( x, p - fmt ));
  2490.     }
  2491.     ++ p;
  2492.     }
  2493.     return found_symbol;
  2494. }
  2495.  
  2496. #include "config/dsp.c"
  2497.